
<!DOCTYPE HTML>
<html lang="" >
    <head>
        <meta charset="UTF-8">
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <title>Implementing Undo History · GitBook</title>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="description" content="">
        <meta name="generator" content="GitBook 3.2.2">
        
        
        
    
    <link rel="stylesheet" href="../gitbook/style.css">

    
            
                
                <link rel="stylesheet" href="../gitbook/gitbook-plugin-highlight/website.css">
                
            
                
                <link rel="stylesheet" href="../gitbook/gitbook-plugin-search/search.css">
                
            
                
                <link rel="stylesheet" href="../gitbook/gitbook-plugin-fontsettings/website.css">
                
            
        

    

    
        
    
        
    
        
    
        
    
        
    
        
    

        
    
    
    <meta name="HandheldFriendly" content="true"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="apple-touch-icon-precomposed" sizes="152x152" href="../gitbook/images/apple-touch-icon-precomposed-152.png">
    <link rel="shortcut icon" href="../gitbook/images/favicon.ico" type="image/x-icon">

    
    <link rel="next" href="IsolatingSubapps.html" />
    
    
    <link rel="prev" href="ComputingDerivedData.html" />
    

    </head>
    <body>
        
<div class="book">
    <div class="book-summary">
        
            
<div id="book-search-input" role="search">
    <input type="text" placeholder="Type to search" />
</div>

            
                <nav role="navigation">
                


<ul class="summary">
    
    

    

    
        
        
    
        <li class="chapter " data-level="1.1" data-path="../">
            
                <a href="../">
            
                    
                    Read Me
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.2" data-path="../introduction/">
            
                <a href="../introduction/">
            
                    
                    Introduction
            
                </a>
            

            
            <ul class="articles">
                
    
        <li class="chapter " data-level="1.2.1" data-path="../introduction/Motivation.html">
            
                <a href="../introduction/Motivation.html">
            
                    
                    Motivation
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.2.2" data-path="../introduction/CoreConcepts.html">
            
                <a href="../introduction/CoreConcepts.html">
            
                    
                    Core Concepts
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.2.3" data-path="../introduction/ThreePrinciples.html">
            
                <a href="../introduction/ThreePrinciples.html">
            
                    
                    Three Principles
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.2.4" data-path="../introduction/PriorArt.html">
            
                <a href="../introduction/PriorArt.html">
            
                    
                    Prior Art
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.2.5" data-path="../introduction/Ecosystem.html">
            
                <a href="../introduction/Ecosystem.html">
            
                    
                    Ecosystem
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.2.6" data-path="../introduction/Examples.html">
            
                <a href="../introduction/Examples.html">
            
                    
                    Examples
            
                </a>
            

            
        </li>
    

            </ul>
            
        </li>
    
        <li class="chapter " data-level="1.3" data-path="../basics/">
            
                <a href="../basics/">
            
                    
                    Basics
            
                </a>
            

            
            <ul class="articles">
                
    
        <li class="chapter " data-level="1.3.1" data-path="../basics/Actions.html">
            
                <a href="../basics/Actions.html">
            
                    
                    Actions
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.3.2" data-path="../basics/Reducers.html">
            
                <a href="../basics/Reducers.html">
            
                    
                    Reducers
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.3.3" data-path="../basics/Store.html">
            
                <a href="../basics/Store.html">
            
                    
                    Store
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.3.4" data-path="../basics/DataFlow.html">
            
                <a href="../basics/DataFlow.html">
            
                    
                    Data Flow
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.3.5" data-path="../basics/UsageWithReact.html">
            
                <a href="../basics/UsageWithReact.html">
            
                    
                    Usage with React
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.3.6" data-path="../basics/ExampleTodoList.html">
            
                <a href="../basics/ExampleTodoList.html">
            
                    
                    Example: Todo List
            
                </a>
            

            
        </li>
    

            </ul>
            
        </li>
    
        <li class="chapter " data-level="1.4" data-path="../advanced/">
            
                <a href="../advanced/">
            
                    
                    Advanced
            
                </a>
            

            
            <ul class="articles">
                
    
        <li class="chapter " data-level="1.4.1" data-path="../advanced/AsyncActions.html">
            
                <a href="../advanced/AsyncActions.html">
            
                    
                    Async Actions
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.4.2" data-path="../advanced/AsyncFlow.html">
            
                <a href="../advanced/AsyncFlow.html">
            
                    
                    Async Flow
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.4.3" data-path="../advanced/Middleware.html">
            
                <a href="../advanced/Middleware.html">
            
                    
                    Middleware
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.4.4" data-path="../advanced/UsageWithReactRouter.html">
            
                <a href="../advanced/UsageWithReactRouter.html">
            
                    
                    Usage with React Router
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.4.5" data-path="../advanced/ExampleRedditAPI.html">
            
                <a href="../advanced/ExampleRedditAPI.html">
            
                    
                    Example: Reddit API
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.4.6" >
            
                <span>
            
                    
                    Next Steps
            
                </span>
            

            
        </li>
    

            </ul>
            
        </li>
    
        <li class="chapter " data-level="1.5" data-path="./">
            
                <a href="./">
            
                    
                    Recipes
            
                </a>
            

            
            <ul class="articles">
                
    
        <li class="chapter " data-level="1.5.1" data-path="MigratingToRedux.html">
            
                <a href="MigratingToRedux.html">
            
                    
                    Migrating to Redux
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.2" data-path="UsingObjectSpreadOperator.html">
            
                <a href="UsingObjectSpreadOperator.html">
            
                    
                    Using Object Spread Operator
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.3" data-path="ReducingBoilerplate.html">
            
                <a href="ReducingBoilerplate.html">
            
                    
                    Reducing Boilerplate
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.4" data-path="ServerRendering.html">
            
                <a href="ServerRendering.html">
            
                    
                    Server Rendering
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.5" data-path="WritingTests.html">
            
                <a href="WritingTests.html">
            
                    
                    Writing Tests
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.6" data-path="ComputingDerivedData.html">
            
                <a href="ComputingDerivedData.html">
            
                    
                    Computing Derived Data
            
                </a>
            

            
        </li>
    
        <li class="chapter active" data-level="1.5.7" data-path="ImplementingUndoHistory.html">
            
                <a href="ImplementingUndoHistory.html">
            
                    
                    Implementing Undo History
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.8" data-path="IsolatingSubapps.html">
            
                <a href="IsolatingSubapps.html">
            
                    
                    Isolating Subapps
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9" data-path="StructuringReducers.html">
            
                <a href="StructuringReducers.html">
            
                    
                    Structuring Reducers
            
                </a>
            

            
            <ul class="articles">
                
    
        <li class="chapter " data-level="1.5.9.1" data-path="reducers/PrerequisiteConcepts.html">
            
                <a href="reducers/PrerequisiteConcepts.html">
            
                    
                    Prerequisite Concepts
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9.2" data-path="reducers/BasicReducerStructure.html">
            
                <a href="reducers/BasicReducerStructure.html">
            
                    
                    Basic Reducer Structure
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9.3" data-path="reducers/SplittingReducerLogic.html">
            
                <a href="reducers/SplittingReducerLogic.html">
            
                    
                    Splitting Reducer Logic
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9.4" data-path="reducers/RefactoringReducersExample.html">
            
                <a href="reducers/RefactoringReducersExample.html">
            
                    
                    Refactoring Reducers Example
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9.5" data-path="reducers/UsingCombineReducers.html">
            
                <a href="reducers/UsingCombineReducers.html">
            
                    
                    Using combineReducers
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9.6" data-path="reducers/BeyondCombineReducers.html">
            
                <a href="reducers/BeyondCombineReducers.html">
            
                    
                    Beyond combineReducers
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9.7" data-path="reducers/NormalizingStateShape.html">
            
                <a href="reducers/NormalizingStateShape.html">
            
                    
                    Normalizing State Shape
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9.8" data-path="reducers/UpdatingNormalizedData.html">
            
                <a href="reducers/UpdatingNormalizedData.html">
            
                    
                    Updating Normalized Data
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9.9" data-path="reducers/ReusingReducerLogic.html">
            
                <a href="reducers/ReusingReducerLogic.html">
            
                    
                    Reusing Reducer Logic
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9.10" data-path="reducers/ImmutableUpdatePatterns.html">
            
                <a href="reducers/ImmutableUpdatePatterns.html">
            
                    
                    Immutable Update Patterns
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.5.9.11" data-path="reducers/InitializingState.html">
            
                <a href="reducers/InitializingState.html">
            
                    
                    Initializing State
            
                </a>
            

            
        </li>
    

            </ul>
            
        </li>
    
        <li class="chapter " data-level="1.5.10" data-path="UsingImmutableJS.html">
            
                <a href="UsingImmutableJS.html">
            
                    
                    Using Immutable.JS with Redux
            
                </a>
            

            
        </li>
    

            </ul>
            
        </li>
    
        <li class="chapter " data-level="1.6" data-path="../FAQ.html">
            
                <a href="../FAQ.html">
            
                    
                    FAQ
            
                </a>
            

            
            <ul class="articles">
                
    
        <li class="chapter " data-level="1.6.1" data-path="../faq/General.html">
            
                <a href="../faq/General.html">
            
                    
                    General
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.6.2" data-path="../faq/Reducers.html">
            
                <a href="../faq/Reducers.html">
            
                    
                    Reducers
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.6.3" data-path="../faq/OrganizingState.html">
            
                <a href="../faq/OrganizingState.html">
            
                    
                    Organizing State
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.6.4" data-path="../faq/StoreSetup.html">
            
                <a href="../faq/StoreSetup.html">
            
                    
                    Store Setup
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.6.5" data-path="../faq/Actions.html">
            
                <a href="../faq/Actions.html">
            
                    
                    Actions
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.6.6" data-path="../faq/ImmutableData.html">
            
                <a href="../faq/ImmutableData.html">
            
                    
                    Immutable Data
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.6.7" data-path="../faq/CodeStructure.html">
            
                <a href="../faq/CodeStructure.html">
            
                    
                    Code Structure
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.6.8" data-path="../faq/Performance.html">
            
                <a href="../faq/Performance.html">
            
                    
                    Performance
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.6.9" data-path="../faq/ReactRedux.html">
            
                <a href="../faq/ReactRedux.html">
            
                    
                    React Redux
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.6.10" data-path="../faq/Miscellaneous.html">
            
                <a href="../faq/Miscellaneous.html">
            
                    
                    Miscellaneous
            
                </a>
            

            
        </li>
    

            </ul>
            
        </li>
    
        <li class="chapter " data-level="1.7" data-path="../Troubleshooting.html">
            
                <a href="../Troubleshooting.html">
            
                    
                    Troubleshooting
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.8" data-path="../Glossary.html">
            
                <a href="../Glossary.html">
            
                    
                    Glossary
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.9" data-path="../api/">
            
                <a href="../api/">
            
                    
                    API Reference
            
                </a>
            

            
            <ul class="articles">
                
    
        <li class="chapter " data-level="1.9.1" data-path="../api/createStore.html">
            
                <a href="../api/createStore.html">
            
                    
                    createStore
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.9.2" data-path="../api/Store.html">
            
                <a href="../api/Store.html">
            
                    
                    Store
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.9.3" data-path="../api/combineReducers.html">
            
                <a href="../api/combineReducers.html">
            
                    
                    combineReducers
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.9.4" data-path="../api/applyMiddleware.html">
            
                <a href="../api/applyMiddleware.html">
            
                    
                    applyMiddleware
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.9.5" data-path="../api/bindActionCreators.html">
            
                <a href="../api/bindActionCreators.html">
            
                    
                    bindActionCreators
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.9.6" data-path="../api/compose.html">
            
                <a href="../api/compose.html">
            
                    
                    compose
            
                </a>
            

            
        </li>
    

            </ul>
            
        </li>
    
        <li class="chapter " data-level="1.10" data-path="../CHANGELOG.md">
            
                <span>
            
                    
                    Change Log
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.11" data-path="../PATRONS.md">
            
                <span>
            
                    
                    Patrons
            
                </a>
            

            
        </li>
    
        <li class="chapter " data-level="1.12" data-path="../Feedback.html">
            
                <a href="../Feedback.html">
            
                    
                    Feedback
            
                </a>
            

            
        </li>
    

    

    <li class="divider"></li>

    <li>
        <a href="https://www.gitbook.com" target="blank" class="gitbook-link">
            Published with GitBook
        </a>
    </li>
</ul>


                </nav>
            
        
    </div>

    <div class="book-body">
        
            <div class="body-inner">
                
                    

<div class="book-header" role="navigation">
    

    <!-- Title -->
    <h1>
        <i class="fa fa-circle-o-notch fa-spin"></i>
        <a href=".." >Implementing Undo History</a>
    </h1>
</div>




                    <div class="page-wrapper" tabindex="-1" role="main">
                        <div class="page-inner">
                            
<div id="book-search-results">
    <div class="search-noresults">
    
                                <section class="normal markdown-section">
                                
                                <h1 id="implementing-undo-history">Implementing Undo History</h1>
<p>Building an Undo and Redo functionality into an app has traditionally required conscious effort from the developer. It is not an easy problem with classical MVC frameworks because you need to keep track of every past <a href="../Glossary.html#state" class="glossary-term" title="">state</a> by cloning all relevant models. In addition, you need to be mindful of the undo stack because the user-initiated changes should be undoable.</p>
<p>This means that implementing Undo and Redo in an MVC application usually forces you to rewrite parts of your application to use a specific data mutation pattern like <a href="https://en.wikipedia.org/wiki/Command_pattern" target="_blank">Command</a>.</p>
<p>With Redux, however, implementing undo history is a breeze. There are three reasons for this:</p>
<ul>
<li>There are no multiple models&#x2014;just a <a href="../Glossary.html#state" class="glossary-term" title="">state</a> subtree that you want to keep track of.</li>
<li>The <a href="../Glossary.html#state" class="glossary-term" title="">state</a> is already immutable, and mutations are already described as discrete actions, which is close to the undo stack mental model.</li>
<li>The <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> <code>(state, action) =&gt; state</code> signature makes it natural to implement generic &#x201C;<a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> enhancers&#x201D; or &#x201C;higher order reducers&#x201D;. They are functions that take your <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> and enhance it with some additional functionality while preserving its signature. Undo history is exactly such a case.</li>
</ul>
<p>Before proceeding, make sure you have worked through the <a href="../basics/">basics tutorial</a> and understand <a href="../basics/Reducers.html">reducer composition</a> well. This recipe will build on top of the example described in the <a href="../basics/">basics tutorial</a>.</p>
<p>In the first part of this recipe, we will explain the underlying concepts that make Undo and Redo possible to implement in a generic way.</p>
<p>In the second part of this recipe, we will show how to use <a href="https://github.com/omnidan/redux-undo" target="_blank">Redux Undo</a> package that provides this functionality out of the box.</p>
<p><a href="https://twitter.com/dan_abramov/status/647038407286390784" target="_blank"><img src="http://i.imgur.com/lvDFHkH.gif" alt="demo of todos-with-undo"></a></p>
<h2 id="understanding-undo-history">Understanding Undo History</h2>
<h3 id="designing-the-state-shape">Designing the State Shape</h3>
<p>Undo history is also part of your app&apos;s <a href="../Glossary.html#state" class="glossary-term" title="">state</a>, and there is no reason why we should approach it differently. Regardless of the type of the <a href="../Glossary.html#state" class="glossary-term" title="">state</a> changing over time, when you implement Undo and Redo, you want to keep track of the <em>history</em> of this <a href="../Glossary.html#state" class="glossary-term" title="">state</a> at different points in time.</p>
<p>For example, the <a href="../Glossary.html#state" class="glossary-term" title="">state</a> shape of a counter app might look like this:</p>
<pre><code class="lang-js">{
  counter: <span class="hljs-number">10</span>
}
</code></pre>
<p>If we wanted to implement Undo and Redo in such an app, we&apos;d need to <a href="../Glossary.html#store" class="glossary-term" title="">store</a> more <a href="../Glossary.html#state" class="glossary-term" title="">state</a> so we can answer the following questions:</p>
<ul>
<li>Is there anything left to undo or redo?</li>
<li>What is the current <a href="../Glossary.html#state" class="glossary-term" title="">state</a>?</li>
<li>What are the past (and future) states in the undo stack?</li>
</ul>
<p>It is reasonable to suggest that our <a href="../Glossary.html#state" class="glossary-term" title="">state</a> shape should change to answer these questions:</p>
<pre><code class="lang-js">{
  counter: {
    past: [ <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span> ],
    present: <span class="hljs-number">10</span>,
    future: []
  }
}
</code></pre>
<p>Now, if user presses &#x201C;Undo&#x201D;, we want it to change to move into the past:</p>
<pre><code class="lang-js">{
  counter: {
    past: [ <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span> ],
    present: <span class="hljs-number">9</span>,
    future: [ <span class="hljs-number">10</span> ]
  }
}
</code></pre>
<p>And further yet:</p>
<pre><code class="lang-js">{
  counter: {
    past: [ <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span> ],
    present: <span class="hljs-number">8</span>,
    future: [ <span class="hljs-number">9</span>, <span class="hljs-number">10</span> ]
  }
}
</code></pre>
<p>When the user presses &#x201C;Redo&#x201D;, we want to move one step back into the future:</p>
<pre><code class="lang-js">{
  counter: {
    past: [ <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span> ],
    present: <span class="hljs-number">9</span>,
    future: [ <span class="hljs-number">10</span> ]
  }
}
</code></pre>
<p>Finally, if the user performs an <a href="../Glossary.html#action" class="glossary-term" title="">action</a> (e.g. decrement the counter) while we&apos;re in the middle of the undo stack, we&apos;re going to discard the existing future:</p>
<pre><code class="lang-js">{
  counter: {
    past: [ <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span> ],
    present: <span class="hljs-number">8</span>,
    future: []
  }
}
</code></pre>
<p>The interesting part here is that it does not matter whether we want to keep an undo stack of numbers, strings, arrays, or objects. The structure will always be the same:</p>
<pre><code class="lang-js">{
  counter: {
    past: [ <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span> ],
    present: <span class="hljs-number">3</span>,
    future: [ <span class="hljs-number">4</span> ]
  }
}
</code></pre>
<pre><code class="lang-js">{
  todos: {
    past: [
      [],
      [ { text: <span class="hljs-string">&apos;Use Redux&apos;</span> } ],
      [ { text: <span class="hljs-string">&apos;Use Redux&apos;</span>, complete: <span class="hljs-literal">true</span> } ]
    ],
    present: [ { text: <span class="hljs-string">&apos;Use Redux&apos;</span>, complete: <span class="hljs-literal">true</span> }, { text: <span class="hljs-string">&apos;Implement Undo&apos;</span> } ],
    future: [
      [ { text: <span class="hljs-string">&apos;Use Redux&apos;</span>, complete: <span class="hljs-literal">true</span> }, { text: <span class="hljs-string">&apos;Implement Undo&apos;</span>, complete: <span class="hljs-literal">true</span> } ]
    ]
  }
}
</code></pre>
<p>In general, it looks like this:</p>
<pre><code class="lang-js">{
  past: <span class="hljs-built_in">Array</span>&lt;T&gt;,
  present: T,
  future: <span class="hljs-built_in">Array</span>&lt;T&gt;
}
</code></pre>
<p>It is also up to us whether to keep a single top-level history:</p>
<pre><code class="lang-js">{
  past: [
    { counterA: <span class="hljs-number">1</span>, counterB: <span class="hljs-number">1</span> },
    { counterA: <span class="hljs-number">1</span>, counterB: <span class="hljs-number">0</span> },
    { counterA: <span class="hljs-number">0</span>, counterB: <span class="hljs-number">0</span> }
  ],
  present: { counterA: <span class="hljs-number">2</span>, counterB: <span class="hljs-number">1</span> },
  future: []
}
</code></pre>
<p>Or many granular histories so user can undo and redo actions in them independently:</p>
<pre><code class="lang-js">{
  counterA: {
    past: [ <span class="hljs-number">1</span>, <span class="hljs-number">0</span> ],
    present: <span class="hljs-number">2</span>,
    future: []
  },
  counterB: {
    past: [ <span class="hljs-number">0</span> ],
    present: <span class="hljs-number">1</span>,
    future: []
  }
}
</code></pre>
<p>We will see later how the approach we take lets us choose how granular Undo and Redo need to be.</p>
<h3 id="designing-the-algorithm">Designing the Algorithm</h3>
<p>Regardless of the specific data type, the shape of the undo history <a href="../Glossary.html#state" class="glossary-term" title="">state</a> is the same:</p>
<pre><code class="lang-js">{
  past: <span class="hljs-built_in">Array</span>&lt;T&gt;,
  present: T,
  future: <span class="hljs-built_in">Array</span>&lt;T&gt;
}
</code></pre>
<p>Let&apos;s talk through the algorithm to manipulate the <a href="../Glossary.html#state" class="glossary-term" title="">state</a> shape described above. We can define two actions to operate on this <a href="../Glossary.html#state" class="glossary-term" title="">state</a>: <code>UNDO</code> and <code>REDO</code>. In our <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a>, we will do the following steps to handle these actions:</p>
<h4 id="handling-undo">Handling Undo</h4>
<ul>
<li>Remove the <em>last</em> element from the <code>past</code>.</li>
<li>Set the <code>present</code> to the element we removed in the previous step.</li>
<li>Insert the old <code>present</code> <a href="../Glossary.html#state" class="glossary-term" title="">state</a> at the <em>beginning</em> of the <code>future</code>.</li>
</ul>
<h4 id="handling-redo">Handling Redo</h4>
<ul>
<li>Remove the <em>first</em> element from the <code>future</code>.</li>
<li>Set the <code>present</code> to the element we removed in the previous step.</li>
<li>Insert the old <code>present</code> <a href="../Glossary.html#state" class="glossary-term" title="">state</a> at the <em>end</em> of the <code>past</code>.</li>
</ul>
<h4 id="handling-other-actions">Handling Other Actions</h4>
<ul>
<li>Insert the <code>present</code> at the end of the <code>past</code>.</li>
<li>Set the <code>present</code> to the new <a href="../Glossary.html#state" class="glossary-term" title="">state</a> after handling the <a href="../Glossary.html#action" class="glossary-term" title="">action</a>.</li>
<li>Clear the <code>future</code>.</li>
</ul>
<h3 id="first-attempt-writing-a-reducer">First Attempt: Writing a Reducer</h3>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> initialState = {
  past: [],
  present: <span class="hljs-literal">null</span>, <span class="hljs-comment">// (?) How do we initialize the present?</span>
  future: []
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">undoable</span>(<span class="hljs-params">state = initialState, action</span>) </span>{
  <span class="hljs-keyword">const</span> { past, present, future } = state

  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">&apos;UNDO&apos;</span>:
      <span class="hljs-keyword">const</span> previous = past[past.length - <span class="hljs-number">1</span>]
      <span class="hljs-keyword">const</span> newPast = past.slice(<span class="hljs-number">0</span>, past.length - <span class="hljs-number">1</span>)
      <span class="hljs-keyword">return</span> {
        past: newPast,
        present: previous,
        future: [ present, ...future ]
      }
    <span class="hljs-keyword">case</span> <span class="hljs-string">&apos;REDO&apos;</span>:
      <span class="hljs-keyword">const</span> next = future[<span class="hljs-number">0</span>]
      <span class="hljs-keyword">const</span> newFuture = future.slice(<span class="hljs-number">1</span>)
      <span class="hljs-keyword">return</span> {
        past: [ ...past, present ],
        present: next,
        future: newFuture
      }
    <span class="hljs-keyword">default</span>:
      <span class="hljs-comment">// (?) How do we handle other actions?</span>
      <span class="hljs-keyword">return</span> state
  }
}
</code></pre>
<p>This implementation isn&apos;t usable because it leaves out three important questions:</p>
<ul>
<li>Where do we get the initial <code>present</code> <a href="../Glossary.html#state" class="glossary-term" title="">state</a> from? We don&apos;t seem to know it beforehand.</li>
<li>Where do we react to the external actions to save the <code>present</code> to the <code>past</code>?</li>
<li>How do we actually delegate the control over the <code>present</code> <a href="../Glossary.html#state" class="glossary-term" title="">state</a> to a custom <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a>?</li>
</ul>
<p>It seems that <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> isn&apos;t the right abstraction, but we&apos;re very close.</p>
<h3 id="meet-reducer-enhancers">Meet Reducer Enhancers</h3>
<p>You might be familiar with <a href="https://en.wikipedia.org/wiki/Higher-order_function" target="_blank">higher order functions</a>. If you use React, you might be familiar with <a href="https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750" target="_blank">higher order components</a>. Here is a variation on the same pattern, applied to reducers.</p>
<p>A <em><a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> enhancer</em> (or a <em>higher order <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a></em>) is a function that takes a <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a>, and returns a new <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> that is able to handle new actions, or to hold more <a href="../Glossary.html#state" class="glossary-term" title="">state</a>, delegating control to the inner <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> for the actions it doesn&apos;t understand. This isn&apos;t a new pattern&#x2014;technically, <a href="../api/combineReducers.html"><code>combineReducers()</code></a> is also a <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> enhancer because it takes reducers and returns a new <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a>.</p>
<p>A <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> enhancer that doesn&apos;t do anything looks like this:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">doNothingWith</span>(<span class="hljs-params">reducer</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">state, action</span>) </span>{
    <span class="hljs-comment">// Just call the passed reducer</span>
    <span class="hljs-keyword">return</span> reducer(state, action)
  }
}
</code></pre>
<p>A <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> enhancer that combines other reducers might look like this:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">combineReducers</span>(<span class="hljs-params">reducers</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">state = {}, action</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.keys(reducers).reduce((nextState, key) =&gt; {
      <span class="hljs-comment">// Call every reducer with the part of the state it manages</span>
      nextState[key] = reducers[key](state[key], action)
      <span class="hljs-keyword">return</span> nextState
    }, {})
  }
}
</code></pre>
<h3 id="second-attempt-writing-a-reducer-enhancer">Second Attempt: Writing a Reducer Enhancer</h3>
<p>Now that we have a better understanding of <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> enhancers, we can see that this is exactly what <code>undoable</code> should have been:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">undoable</span>(<span class="hljs-params">reducer</span>) </span>{
  <span class="hljs-comment">// Call the reducer with empty action to populate the initial state</span>
  <span class="hljs-keyword">const</span> initialState = {
    past: [],
    present: reducer(<span class="hljs-literal">undefined</span>, {}),
    future: []
  }

  <span class="hljs-comment">// Return a reducer that handles undo and redo</span>
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">state = initialState, action</span>) </span>{
    <span class="hljs-keyword">const</span> { past, present, future } = state

    <span class="hljs-keyword">switch</span> (action.type) {
      <span class="hljs-keyword">case</span> <span class="hljs-string">&apos;UNDO&apos;</span>:
        <span class="hljs-keyword">const</span> previous = past[past.length - <span class="hljs-number">1</span>]
        <span class="hljs-keyword">const</span> newPast = past.slice(<span class="hljs-number">0</span>, past.length - <span class="hljs-number">1</span>)
        <span class="hljs-keyword">return</span> {
          past: newPast,
          present: previous,
          future: [ present, ...future ]
        }
      <span class="hljs-keyword">case</span> <span class="hljs-string">&apos;REDO&apos;</span>:
        <span class="hljs-keyword">const</span> next = future[<span class="hljs-number">0</span>]
        <span class="hljs-keyword">const</span> newFuture = future.slice(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">return</span> {
          past: [ ...past, present ],
          present: next,
          future: newFuture
        }
      <span class="hljs-keyword">default</span>:
        <span class="hljs-comment">// Delegate handling the action to the passed reducer</span>
        <span class="hljs-keyword">const</span> newPresent = reducer(present, action)
        <span class="hljs-keyword">if</span> (present === newPresent) {
          <span class="hljs-keyword">return</span> state
        }
        <span class="hljs-keyword">return</span> {
          past: [ ...past, present ],
          present: newPresent,
          future: []
        }
    }
  }
}
</code></pre>
<p>We can now wrap any <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> into <code>undoable</code> <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> enhancer to teach it to react to <code>UNDO</code> and <code>REDO</code> actions.</p>
<pre><code class="lang-js"><span class="hljs-comment">// This is a reducer</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">todos</span>(<span class="hljs-params">state = [], action</span>) </span>{
  <span class="hljs-comment">/* ... */</span>
}

<span class="hljs-comment">// This is also a reducer!</span>
<span class="hljs-keyword">const</span> undoableTodos = undoable(todos)

<span class="hljs-keyword">import</span> { createStore } <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;redux&apos;</span>
<span class="hljs-keyword">const</span> store = createStore(undoableTodos)

store.dispatch({
  type: <span class="hljs-string">&apos;ADD_TODO&apos;</span>,
  text: <span class="hljs-string">&apos;Use Redux&apos;</span>
})

store.dispatch({
  type: <span class="hljs-string">&apos;ADD_TODO&apos;</span>,
  text: <span class="hljs-string">&apos;Implement Undo&apos;</span>
})

store.dispatch({
  type: <span class="hljs-string">&apos;UNDO&apos;</span>
})
</code></pre>
<p>There is an important gotcha: you need to remember to append <code>.present</code> to the current <a href="../Glossary.html#state" class="glossary-term" title="">state</a> when you retrieve it. You may also check <code>.past.length</code> and <code>.future.length</code> to determine whether to enable or to disable the Undo and Redo buttons, respectively.</p>
<p>You might have heard that Redux was influenced by <a href="https://github.com/evancz/elm-architecture-tutorial/" target="_blank">Elm Architecture</a>. It shouldn&apos;t come as a surprise that this example is very similar to <a href="http://package.elm-lang.org/packages/TheSeamau5/elm-undo-redo/2.0.0" target="_blank">elm-undo-redo package</a>.</p>
<h2 id="using-redux-undo">Using Redux Undo</h2>
<p>This was all very informative, but can&apos;t we just drop a library and use it instead of implementing <code>undoable</code> ourselves? Sure, we can! Meet <a href="https://github.com/omnidan/redux-undo" target="_blank">Redux Undo</a>, a library that provides simple Undo and Redo functionality for any part of your Redux tree.</p>
<p>In this part of the recipe, you will learn how to make the <a href="http://redux.js.org/docs/basics/ExampleTodoList.html" target="_blank">Todo List example</a> undoable. You can find the full source of this recipe in the <a href="https://github.com/reactjs/redux/tree/master/examples/todos-with-undo" target="_blank"><code>todos-with-undo</code> example that comes with Redux</a>.</p>
<h3 id="installation">Installation</h3>
<p>First of all, you need to run</p>
<pre><code>npm install --save redux-undo
</code></pre><p>This installs the package that provides the <code>undoable</code> <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> enhancer.</p>
<h3 id="wrapping-the-reducer">Wrapping the Reducer</h3>
<p>You will need to wrap the <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> you wish to enhance with <code>undoable</code> function. For example, if you exported a <code>todos</code> <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> from a dedicated file, you will want to change it to export the result of calling <code>undoable()</code> with the <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> you wrote:</p>
<h4 id="reducerstodosjs"><code>reducers/todos.js</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> undoable, { distinctState } <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;redux-undo&apos;</span>

<span class="hljs-comment">/* ... */</span>

<span class="hljs-keyword">const</span> todos = (state = [], action) =&gt; {
  <span class="hljs-comment">/* ... */</span>
}

<span class="hljs-keyword">const</span> undoableTodos = undoable(todos, {
  filter: distinctState()
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> undoableTodos
</code></pre>
<p>The <code>distinctState()</code> filter serves to ignore the actions that didn&apos;t result in a <a href="../Glossary.html#state" class="glossary-term" title="">state</a> change. There are <a href="https://github.com/omnidan/redux-undo#configuration" target="_blank">many other options</a> to configure your undoable <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a>, like setting the <a href="../Glossary.html#action" class="glossary-term" title="">action</a> type for Undo and Redo actions.</p>
<p>Note that your <code>combineReducers()</code> call will stay exactly as it was, but the <code>todos</code> <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> will now refer to the <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> enhanced with Redux Undo:</p>
<h4 id="reducersindexjs"><code>reducers/index.js</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { combineReducers } <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;redux&apos;</span>
<span class="hljs-keyword">import</span> todos <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;./todos&apos;</span>
<span class="hljs-keyword">import</span> visibilityFilter <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;./visibilityFilter&apos;</span>

<span class="hljs-keyword">const</span> todoApp = combineReducers({
  todos,
  visibilityFilter
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> todoApp
</code></pre>
<p>You may wrap one or more reducers in <code>undoable</code> at any level of the <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> composition hierarchy. We choose to wrap <code>todos</code> instead of the top-level combined <a href="../Glossary.html#reducer" class="glossary-term" title="">reducer</a> so that changes to <code>visibilityFilter</code> are not reflected in the undo history.</p>
<h3 id="updating-the-selectors">Updating the Selectors</h3>
<p>Now the <code>todos</code> part of the <a href="../Glossary.html#state" class="glossary-term" title="">state</a> looks like this:</p>
<pre><code class="lang-js">{
  visibilityFilter: <span class="hljs-string">&apos;SHOW_ALL&apos;</span>,
  todos: {
    past: [
      [],
      [ { text: <span class="hljs-string">&apos;Use Redux&apos;</span> } ],
      [ { text: <span class="hljs-string">&apos;Use Redux&apos;</span>, complete: <span class="hljs-literal">true</span> } ]
    ],
    present: [ { text: <span class="hljs-string">&apos;Use Redux&apos;</span>, complete: <span class="hljs-literal">true</span> }, { text: <span class="hljs-string">&apos;Implement Undo&apos;</span> } ],
    future: [
      [ { text: <span class="hljs-string">&apos;Use Redux&apos;</span>, complete: <span class="hljs-literal">true</span> }, { text: <span class="hljs-string">&apos;Implement Undo&apos;</span>, complete: <span class="hljs-literal">true</span> } ]
    ]
  }
}
</code></pre>
<p>This means you need to access your <a href="../Glossary.html#state" class="glossary-term" title="">state</a> with <code>state.todos.present</code> instead of
just <code>state.todos</code>:</p>
<h4 id="containersvisibletodolistjs"><code>containers/VisibleTodoList.js</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mapStateToProps = (state) =&gt; {
  <span class="hljs-keyword">return</span> {
    todos: getVisibleTodos(state.todos.present, state.visibilityFilter)
  }
}
</code></pre>
<h3 id="adding-the-buttons">Adding the Buttons</h3>
<p>Now all you need to do is add the buttons for the Undo and Redo actions.</p>
<p>First, create a new container component called <code>UndoRedo</code> for these buttons. We won&apos;t bother to split the presentational part into a separate file because it is very small:</p>
<h4 id="containersundoredojs"><code>containers/UndoRedo.js</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react&apos;</span>

<span class="hljs-comment">/* ... */</span>

<span class="hljs-keyword">let</span> UndoRedo = ({ canUndo, canRedo, onUndo, onRedo }) =&gt; (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onUndo}</span> <span class="hljs-attr">disabled</span>=<span class="hljs-string">{!canUndo}</span>&gt;</span>
      Undo
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onRedo}</span> <span class="hljs-attr">disabled</span>=<span class="hljs-string">{!canRedo}</span>&gt;</span>
      Redo
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)
</code></pre>
<p>You will use <code>connect()</code> from <a href="https://github.com/reactjs/react-redux" target="_blank">React Redux</a> to generate a container component. To determine whether to enable Undo and Redo buttons, you can check <code>state.todos.past.length</code> and <code>state.todos.future.length</code>. You won&apos;t need to write <a href="../Glossary.html#action" class="glossary-term" title="">action</a> creators for performing undo and redo because Redux Undo already provides them:</p>
<h4 id="containersundoredojs"><code>containers/UndoRedo.js</code></h4>
<pre><code class="lang-js"><span class="hljs-comment">/* ... */</span>

<span class="hljs-keyword">import</span> { ActionCreators <span class="hljs-keyword">as</span> UndoActionCreators } <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;redux-undo&apos;</span>
<span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react-redux&apos;</span>

<span class="hljs-comment">/* ... */</span>

<span class="hljs-keyword">const</span> mapStateToProps = (state) =&gt; {
  <span class="hljs-keyword">return</span> {
    canUndo: state.todos.past.length &gt; <span class="hljs-number">0</span>,
    canRedo: state.todos.future.length &gt; <span class="hljs-number">0</span>
  }
}

<span class="hljs-keyword">const</span> mapDispatchToProps = (dispatch) =&gt; {
  <span class="hljs-keyword">return</span> {
    onUndo: () =&gt; dispatch(UndoActionCreators.undo()),
    onRedo: () =&gt; dispatch(UndoActionCreators.redo())
  }
}

UndoRedo = connect(
  mapStateToProps,
  mapDispatchToProps
)(UndoRedo)

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UndoRedo
</code></pre>
<p>Now you can add <code>UndoRedo</code> component to the <code>App</code> component:</p>
<h4 id="componentsappjs"><code>components/App.js</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;react&apos;</span>
<span class="hljs-keyword">import</span> Footer <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;./Footer&apos;</span>
<span class="hljs-keyword">import</span> AddTodo <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;../containers/AddTodo&apos;</span>
<span class="hljs-keyword">import</span> VisibleTodoList <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;../containers/VisibleTodoList&apos;</span>
<span class="hljs-keyword">import</span> UndoRedo <span class="hljs-keyword">from</span> <span class="hljs-string">&apos;../containers/UndoRedo&apos;</span>

<span class="hljs-keyword">const</span> App = () =&gt; (
  &lt;div&gt;
    &lt;AddTodo /&gt;
    &lt;VisibleTodoList /&gt;
    &lt;Footer /&gt;
    &lt;UndoRedo /&gt;
  &lt;/div&gt;
)

export default App
</code></pre>
<p>This is it! Run <code>npm install</code> and <code>npm start</code> in the <a href="https://github.com/reactjs/redux/tree/master/examples/todos-with-undo" target="_blank">example folder</a> and try it out!</p>

                                
                                </section>
                            
    </div>
    <div class="search-results">
        <div class="has-results">
            
            <h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
            <ul class="search-results-list"></ul>
            
        </div>
        <div class="no-results">
            
            <h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
            
        </div>
    </div>
</div>

                        </div>
                    </div>
                
            </div>

            
                
                <a href="ComputingDerivedData.html" class="navigation navigation-prev " aria-label="Previous page: Computing Derived Data">
                    <i class="fa fa-angle-left"></i>
                </a>
                
                
                <a href="IsolatingSubapps.html" class="navigation navigation-next " aria-label="Next page: Isolating Subapps">
                    <i class="fa fa-angle-right"></i>
                </a>
                
            
        
    </div>

    <script>
        var gitbook = gitbook || [];
        gitbook.push(function() {
            gitbook.page.hasChanged({"page":{"title":"Implementing Undo History","level":"1.5.7","depth":2,"next":{"title":"Isolating Subapps","level":"1.5.8","depth":2,"path":"recipes/IsolatingSubapps.md","ref":"./recipes/IsolatingSubapps.md","articles":[]},"previous":{"title":"Computing Derived Data","level":"1.5.6","depth":2,"path":"recipes/ComputingDerivedData.md","ref":"./recipes/ComputingDerivedData.md","articles":[]},"dir":"ltr"},"config":{"gitbook":"*","theme":"default","variables":{},"plugins":["livereload"],"pluginsConfig":{"livereload":{},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"}},"file":{"path":"recipes/ImplementingUndoHistory.md","mtime":"2017-03-13T14:28:11.335Z","type":"markdown"},"gitbook":{"version":"3.2.2","time":"2017-03-15T14:47:19.389Z"},"basePath":"..","book":{"language":""}});
        });
    </script>
</div>

        
    <script src="../gitbook/gitbook.js"></script>
    <script src="../gitbook/theme.js"></script>
    
        
        <script src="../gitbook/gitbook-plugin-livereload/plugin.js"></script>
        
    
        
        <script src="../gitbook/gitbook-plugin-search/search-engine.js"></script>
        
    
        
        <script src="../gitbook/gitbook-plugin-search/search.js"></script>
        
    
        
        <script src="../gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
        
    
        
        <script src="../gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
        
    
        
        <script src="../gitbook/gitbook-plugin-sharing/buttons.js"></script>
        
    
        
        <script src="../gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script>
        
    

    </body>
</html>

